package cn.com.huzo.service.tech.impl;

import cn.com.huzo.model.entities.tech.MrpHeaderEntity;
import cn.com.huzo.model.entities.tech.MrpLinesResultEntity;
import cn.com.huzo.repository.tech.MrpHeaderRepository;
import huzofw.service.impl.GenericManagerImpl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.com.huzo.repository.tech.MrpLinesAssortmentRepository;
import cn.com.huzo.repository.tech.MrpLinesResultRepository;
import cn.com.huzo.repository.tech.PieceYardageLinesProductColourRepository;
import cn.com.huzo.repository.trade.ProductionInstructionLinesDestinationRepository;
import cn.com.huzo.repository.trade.ProductionInstructionLinesDestinationSchemaRepository;
import cn.com.huzo.repository.trade.ProductionInstructionLinesRepository;
import cn.com.huzo.service.tech.MrpLinesResultManager;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import huzofw.model.entities.paginator.Paginator;
import org.apache.commons.collections4.MapUtils;

/**
 * 物料需求计划-材料需求明细管理服务对象类实现。
 *
 * @author 吴旭
 */
@Service("MrpLinesResultManager")
public class MrpLinesResultManagerImpl extends GenericManagerImpl<MrpLinesResultEntity, String>
        implements MrpLinesResultManager {

    @Resource(name = "MrpHeaderRepository")
    private MrpHeaderRepository _dao;

    @Resource(name = "MrpLinesAssortmentRepository")
    private MrpLinesAssortmentRepository _dao_lines_assortment;

    @Resource(name = "MrpLinesResultRepository")
    private MrpLinesResultRepository _dao_lines_result;

    @Resource(name = "ProductionInstructionLinesRepository")
    private ProductionInstructionLinesRepository _dao_mo_lines;

    @Resource(name = "ProductionInstructionLinesDestinationSchemaRepository")
    private ProductionInstructionLinesDestinationSchemaRepository _dao_mo_lines_schedule;

    @Resource(name = "ProductionInstructionLinesDestinationRepository")
    private ProductionInstructionLinesDestinationRepository _dao_mo_lines_destination;

    @Resource(name = "PieceYardageLinesProductColourRepository")
    private PieceYardageLinesProductColourRepository _dao_bom_lines_product_colour;

    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Override
    @Transactional
    public List<MrpLinesResultEntity> fetchByHeaderId(Long headerId) throws Exception {
        return _dao_lines_result.fetchByHeaderId(headerId);
    }

    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Override
    @Transactional
    public List<Map<String, Object>> fetchForStockOut(Map<String, Object> paramsMap) throws Exception {
        return _dao_lines_result.fetchForStockOut(paramsMap);
    }

    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Override
    @Transactional
    public List<MrpLinesResultEntity> fetchByAssortmentType(Long headerId, Short assortmentType, Short sortType) throws Exception {
        return _dao_lines_result.fetchByAssortmentType(headerId, assortmentType, sortType);
    }

    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Override
    @Transactional
    public Map<String, Object> fetchForPage(Map<String, Object> criterion) throws Exception {
        Map<String, Object> _result = new HashMap();

        Long offset = (long) (MapUtils.getInteger(criterion, "Limit") * (MapUtils.getInteger(criterion, "PageIndex") - 1));
        criterion.put("Offset", offset);

        long total = _dao_lines_result.fetchForCount(criterion);

        if (total > 0) {
            List<MrpLinesResultEntity> itemList = _dao_lines_result.fetchForPage(criterion);
            Paginator<MrpLinesResultEntity> paginator = new Paginator<>(itemList, offset, MapUtils.getInteger(criterion, "Limit"), total);

            _result.put("TotalRecordCount", paginator.getTotal());
            _result.put("TotalPages", paginator.getTotalPages());
            _result.put("PageIndex", paginator.getPageIndex());
            _result.put("DataList", paginator.getItemList());
            _result.put("Success", true);
        } else {
            _result.put("Success", false);
        }

        return _result;
    }

    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Override
    @Transactional
    public List<String> fetchAllSelectedLines(Map<String, Object> criterion) throws Exception {
        return _dao_lines_result.fetchAllSelectedLines(criterion);
    }

    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Transactional
    @Override
    public Map<String, Object> batchUpdate(Map<String, Object> criterion) throws Exception {
        // 分解上传数据
        ObjectMapper mapper = new ObjectMapper();
        List<MrpLinesResultEntity> itemList = mapper.convertValue(MapUtils.getObject(criterion, "LinesList"), new TypeReference<List<MrpLinesResultEntity>>() {
        });

        Integer rowsAffected = _dao_lines_result.batchUpdate(itemList);
        // 审计日志
        if (rowsAffected > 0) {
            writeAuditLog(MapUtils.getLong(criterion, "UpdatedBy"),
                    "技术管理→物料需求计划明细", MapUtils.getString(criterion, "StyleNo"),
                    "更新明细");
        }

        Map<String, Object> _result = new HashMap();
        _result.put("MrpLinesList", _dao_lines_result.fetchByHeaderId(MapUtils.getLong(criterion, "HeaderId")));

        return _result;
    }

    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Transactional
    @Override
    public Map<String, Object> reCalculate(Long headerId, Short billType,
            Long bomHeaderId, Long moHeaderId, String styleNo, Long updatedBy) throws Exception {
        // 第一步，同步搭配明细表与单耗表（新增材料默认搭配类型 = 9）
        _dao_lines_assortment.deleteLinesForSyncBom(headerId, bomHeaderId);
        _dao_lines_assortment.insertLinesForSyncBom(headerId, bomHeaderId, updatedBy);

        // 第二步，对于上面插入的数据做无搭配计算
        _dao_lines_assortment.batchAssort(headerId, moHeaderId, styleNo, (short) 9);

        // 第三步，将上面插入的数据类型改为0（无搭配）
        _dao_lines_assortment.updateTypeForNewLines(headerId, updatedBy);

        // 第四步，更新物料需求明细中的成品数（如果生产指示书有变化）
        Map<String, Object> criterion = new HashMap();
        criterion.put("HeaderId", headerId);
        criterion.put("MoHeaderId", moHeaderId);
        criterion.put("StyleNo", styleNo);
        Integer hasDestination = _dao_mo_lines_schedule.fetchForCountForDestination(moHeaderId);
        if (hasDestination > 0) {
            _dao_lines_result.updateProductQuantityWithDestination(criterion);
        } else {
            _dao_lines_result.updateProductQuantity(criterion);
        }

        // 第五步，重新计算物料需求量（补给数数）
        criterion.clear();
        criterion.put("HeaderId", headerId);
        criterion.put("UpdatedBy", updatedBy);
        Integer rowsAffected = _dao_lines_result.reCalculate(criterion);

        // 第六步，如果是定版调达，还要计算提前组料数，然后再计算补给数
        if (billType == 1) {
            // 取得提前组料单
            MrpHeaderEntity _prior_instance = _dao.fetchPriorMrpByStyleNo(styleNo, moHeaderId);
            if (_prior_instance != null) {
                // 通过提前组料单更新定版调达的提前组料数、规格、备注，并重新计算补给数
                _dao_lines_result.updateByPriorMrpLines(headerId, _prior_instance.getHeaderId(), updatedBy);
            }
        }
        // 如果是提前组料，还要看是否更新相应的定版调达数，然后再计算补给数
        if (billType == 0) {
            // 取得提前组料单
            MrpHeaderEntity _final_instance = _dao.fetchFinalMrpByStyleNo(styleNo, moHeaderId);
            if (_final_instance != null) {
                // 通过提前组料单更新定版调达的提前组料数、规格、备注，并重新计算补给数
                _dao_lines_result.updateByPriorMrpLines(_final_instance.getHeaderId(), headerId, updatedBy);
            }
        }

        // 审计日志
        if (rowsAffected > 0) {
            writeAuditLog(updatedBy, "技术管理→物料需求计划（主辅料）", "[款号]：" + styleNo, "重新计算");
        }

        // 得到重新计算后的返回值
        Map<String, Object> _result = new HashMap();
        _result.put("ScheduleNode", _dao_mo_lines_schedule.fetchScheduleDateNode(moHeaderId));
        _result.put("DestinationNode", _dao_mo_lines_destination.fetchProductionInstructionLinesDestinationNode(moHeaderId));
        _result.put("MoLinesList", _dao_mo_lines.fetchLinesByHeaderIdAndStyleNo(moHeaderId, styleNo));
        // 取得搭配明细（计算用单耗明细）
        _result.put("AssortmentLinesList", _dao_lines_assortment.fetchByHeaderId(headerId));
        // 取得计算用单耗明细用成品色
        _result.put("ProductColourNode", _dao_bom_lines_product_colour.fetchByHeaderKey(bomHeaderId));
        // 取得材料用量明细
        _result.put("MrpLinesList", _dao_lines_result.fetchByHeaderId(headerId));

        return _result;
    }

    // <editor-fold defaultstate="collapsed" desc="订单相关用">
    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Transactional
    @Override
    public List<Map<String, Object>> fetchRoundCardQuantityFromMrpByPoHeaderId(Long poHeaderId) throws Exception {
        return _dao_lines_result.fetchRoundCardQuantityFromMrpByPoHeaderId(poHeaderId);
    }

    /**
     * {@inheritDoc}
     *
     * @throws java.lang.Exception
     */
    @Transactional
    @Override
    public List<Map<String, Object>> fetchHangerStickerQuantityFromMrpByPoHeaderId(Long poHeaderId) throws Exception {
        return _dao_lines_result.fetchHangerStickerQuantityFromMrpByPoHeaderId(poHeaderId);
    }
    // </editor-fold>
}
